#ifndef __CROSSFIRE_MATH_PLAIN
#define __CROSSFIRE_MATH_PLAIN

#include "Ray.h"

namespace Math
{
	class CCF_Plane
	{
	public:
		D3DXVECTOR3 n;
		float    dist;

		CCF_Plane(const D3DXVECTOR3& normal, float d) : n (normal)
		{
		    D3DXVec3Normalize(&n, &n);
			dist = d;
		}

		CCF_Plane(const D3DXVECTOR3& normal, const D3DXVECTOR3& point) : n (normal)
		{
			D3DXVec3Normalize(&n, &n);
			dist = -(D3DXVec3Dot(&point, &n));
		}

		CCF_Plane(const D3DXVECTOR3& p1, const D3DXVECTOR3& p2, const D3DXVECTOR3& p3)
		{
			D3DXVec3Cross(&n, &(p2 - p1), &(p3 - p1));

			D3DXVec3Normalize(&n, &n);

			dist = -(D3DXVec3Dot(&p1, &n));
		}

		float signedDistanceTo(const D3DXVECTOR3& v) const
		{
			return D3DXVec3Dot(&v, &n) + dist;
		}

		float distanceTo(const D3DXVECTOR3& v) const
		{
			return (float)fabs(signedDistanceTo(v));
		}

		D3DXVECTOR3 getPointOnPlane () const
		{
			return (-dist) * n;
		}

	// classify point
		int	classify(const D3DXVECTOR3& p) const
		{
			float   v = signedDistanceTo(p);

			if (v > EPSILON)
				return IN_FRONT;
			else
			if (v < -EPSILON)
				return IN_BACK;
			return IN_PLANE;
		}
	
		void flip()
		{
			n    = -n;
			dist = -dist;
		}

		bool intersectByRay(const D3DXVECTOR3& org, const D3DXVECTOR3& dir, float& t) const
		{
			float   numer = -(dist + D3DXVec3Dot(&org, &n));
			float   denom = D3DXVec3Dot(&dir, &n);

			if ( fabs ( denom ) < EPSILON )
			return false;

			t = numer / denom;

			return true;
		}

		/*bool intersectByRay(const CCF_Ray& ray, float& t) const
		{
			float	numer = -(dist + D3DXVec3Dot(&ray.getOrigin(), &n));
			float	denom = D3DXVec3Dot(&ray.getDir(), &n);

			if ( fabs ( denom ) < EPSILON )
				return false;

			t = numer / denom;

			return true;
		}*/
	};
};


#endif